import joblib
import redis
import pandas as pd
from fastapi import APIRouter, Depends, HTTPException, Query
from datetime import datetime, date, timedelta
from typing import List
import time

from ..schemas import predictions as schemas_preds

# --- 1. 加载模型和配置 ---

# 加载我们训练好的模型
try:
    model = joblib.load("backend/server/models/net_flow_predictor.joblib")
except FileNotFoundError:
    model = None # 如果找不到模型，则设为 None

# 连接 Redis，用于获取历史数据
redis_client = redis.Redis(host='localhost', port=6379, db=0, decode_responses=True)

# 模型需要的历史窗口大小
LAG_WINDOW_SIZE = 48

router = APIRouter(
    prefix="/api/v1/predictions",
    tags=["Predictions"],
)

# --- 2. 辅助函数：创建特征 ---

def create_features_for_timestamp(ts: datetime, community_id: int, history: List[float]) -> pd.DataFrame:
    """为单个时间点创建模型所需的特征 DataFrame"""
    data = {
        'community_id': [community_id],
        'hour': [ts.hour],
        'minute': [ts.minute],
        'day_of_week': [ts.weekday()],
        'is_weekend': [1 if ts.weekday() >= 5 else 0],
        'time_slot_of_day': [ts.hour * 2 + ts.minute // 30]
    }
    # 添加历史窗口特征
    for i in range(1, LAG_WINDOW_SIZE + 1):
        data[f'net_flow_lag_{i}'] = [history[-i]]
        
    return pd.DataFrame(data)

# --- 3. API 路由实现 ---

@router.get("/daily-netflow", response_model=schemas_preds.DailyPredictionResponse)
def get_daily_netflow_prediction(
    # 使用 Query 来给参数添加描述和示例
    query_date: date = Query(..., description="需要基于此日期的数据进行预测，格式：YYYY-MM-DD", example="2021-05-13")
):
    """
    根据指定日期的数据，预测未来一整天的净流量。
    """
    if model is None:
        raise HTTPException(status_code=503, detail="预测模型未加载，服务不可用。")
    
    print(f"Received request for daily netflow prediction for date: {query_date.isoformat()}")
    start_time = time.time()

    # --- 准备预测所需的数据和时间 ---
    prediction_start_time = datetime.combine(query_date, datetime.min.time()) + timedelta(days=1)
    all_community_predictions = []

    # --- 对每个社区进行滚动预测 ---
    for cid in range(1, 75): # 遍历所有社区
        
        # a. 获取用于启动预测的历史数据 (query_date 当天的48个槽)
        history_window = []
        redis_key = f"community:{cid}:netflow"
        current_slot = datetime.combine(query_date, datetime.min.time())
        for _ in range(LAG_WINDOW_SIZE):
            net_flow_str = redis_client.hget(redis_key, current_slot.isoformat())
            history_window.append(int(net_flow_str) if net_flow_str else 0)
            current_slot += timedelta(minutes=30)
        
        # b. 开始滚动预测未来48个时间槽
        community_series = []
        prediction_target_time = prediction_start_time
        for _ in range(48):
            # 创建当前时间点的特征
            features = create_features_for_timestamp(prediction_target_time, cid, history_window)
            
            # 进行单步预测
            predicted_value = model.predict(features)[0]
            
            # 保存预测结果
            community_series.append({
                "time_slot": prediction_target_time,
                "predicted_net_flow": predicted_value
            })
            
            # 关键：更新历史窗口，为下一步预测做准备
            # 移除最老的数据，添加最新的预测数据
            history_window.pop(0)
            history_window.append(predicted_value)
            
            # 时间前进到下一个槽
            prediction_target_time += timedelta(minutes=30)
            
        all_community_predictions.append({
            "community_id": cid,
            "series": community_series
        })

    response_data = {
        "prediction_for_date": prediction_start_time.date(),
        "predictions": all_community_predictions
    }
    end_time = time.time()
    print(f"Processed daily netflow prediction request in {end_time - start_time:.3f} seconds")
    
    return {"code": 0, "message": "success", "data": response_data}